package com.futu.common.service.impl;

import com.alibaba.fastjson.JSON;

import com.futu.common.service.WeatherService;
import com.futu.common.utils.Constants;
import com.futu.common.utils.HttpClientUtil;
import com.futu.common.utils.RedisUtil;
import com.futu.common.vo.WeatherForecastVO;
import com.futu.common.vo.WeatherRealTimeVO;
import com.futu.kafka.TemperatureReading;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class WeatherServiceImpl implements WeatherService {

    @Resource
    private RedisUtil redisUtil;

    // 高德地图Key，需替换为你申请的
    private static final String AMAP_KEY = "cbbb13cd8839a33a693a9d10c4fbe070";

    // 高德地理编码API
    private static final String GEOCODE_URL = "https://restapi.amap.com/v3/geocode/geo";

    @Autowired
    private KafkaTemplate kafkaTemplate;

    // 实现接口方法（保持原有参数不变）
    @Override
    public WeatherRealTimeVO getCurrentWeather(String scenicSpotId, String cityCode) {
        // 优先使用cityCode
        if (StringUtils.hasText(cityCode)) {
            return getCurrentWeatherByCityCode(cityCode);
        }

        // 如果cityCode为空，尝试从景点ID获取城市信息（需要你自己实现）
        return null; // 或抛出异常，根据你的业务逻辑处理
    }

    // 实现接口方法（保持原有参数不变）
    @Override
    public WeatherForecastVO getWeatherForecast(String scenicSpotId, String cityCode) {
        if (StringUtils.hasText(cityCode)) {
            return getWeatherForecastByCityCode(cityCode);
        }

        // 如果cityCode为空，尝试从景点ID获取城市信息
        return null;
    }

    // 新增：通过城市名称查询实时天气
    public WeatherRealTimeVO getCurrentWeatherByCityName(String cityName) {
        // 防御性清洗和日志
        System.out.println("收到的cityName参数: " + cityName);
        if (cityName == null) return null;

        try {
            // 尝试URL解码（如果是URL编码格式）
            if (cityName.contains("%")) {
                cityName = java.net.URLDecoder.decode(cityName, "UTF-8");
                System.out.println("URL解码后的cityName: " + cityName);
            }
        } catch (Exception e) {
            System.err.println("URL解码异常: " + e.getMessage());
        }

        cityName = cityName.trim();
        // 只保留常见汉字、英文字母、数字和空格
        cityName = cityName.replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9·\\s]", "");
        if (cityName.isEmpty()) return null;

        String cacheKey = Constants.WEATHER_REALTIME_CACHE_KEY + cityName;
        String cacheData = null;

        try {
            // 尝试从Redis获取缓存数据
            cacheData = redisUtil.get(cacheKey);
            if (StringUtils.hasText(cacheData)) {
                try {
                    return JSON.parseObject(cacheData, WeatherRealTimeVO.class);
                } catch (Exception e) {
                    System.err.println("Redis缓存数据反序列化失败，将清除缓存: " + e.getMessage());
                    System.err.println("缓存数据内容: " + cacheData);
                    // 清除损坏的缓存数据
                    redisUtil.delete(cacheKey);
                    // 尝试清除所有可能相关的缓存
                    try {
                        // 清除可能的城市编码缓存
                        String cityCode = getCityCodeByCityName(cityName);
                        if (cityCode != null) {
                            redisUtil.delete(Constants.WEATHER_REALTIME_CACHE_KEY + cityCode);
                        }
                    } catch (Exception ex) {
                        // 忽略清除过程中的异常
                    }
                }
            }
        } catch (Exception e) {
            System.err.println("Redis缓存读取异常: " + e.getMessage());
            e.printStackTrace();
            // 尝试主动清除可能损坏的缓存
            try {
                redisUtil.delete(cacheKey);
            } catch (Exception ex) {
                // 忽略清除过程中的异常
            }
            // 发生异常时，继续执行后续代码获取新数据
        }

        String cityCode = getCityCodeByCityName(cityName);
        if (cityCode == null) {
            System.err.println("无法获取城市编码，cityName: " + cityName);
            return null;
        }
        System.out.println("获取到城市编码: " + cityCode + " (城市: " + cityName + ")");

        WeatherRealTimeVO result = getCurrentWeatherByCityCode(cityCode);
        if (result != null) {
            try {
                // 将对象转为JSON字符串存入Redis
                redisUtil.set(cacheKey, JSON.toJSONString(result), 7200); // 缓存2小时

                // 打印返回给前端的天气数据
                System.out.println("========== 返回给前端的天气数据 ==========");
                System.out.println("城市: " + result.getCity());
                System.out.println("天气: " + result.getWeather());
                System.out.println("温度: " + result.getTemperature() + "℃");
                System.out.println("风向: " + result.getWindDirection());
                System.out.println("风力: " + result.getWindPower());
                System.out.println("湿度: " + result.getHumidity());
                System.out.println("报告时间: " + result.getReportTime());
                System.out.println("=========================================");
            } catch (Exception e) {
                System.err.println("Redis缓存写入异常: " + e.getMessage());
                e.printStackTrace();
            }
        }
        return result;
    }

    // 新增：通过城市名称查询天气预报
    public WeatherForecastVO getWeatherForecastByCityName(String cityName) {
        // 防御性清洗和日志
        System.out.println("收到的cityName参数(预报): " + cityName);
        if (cityName == null) return null;

        try {
            // 尝试URL解码（如果是URL编码格式）
            if (cityName.contains("%")) {
                cityName = java.net.URLDecoder.decode(cityName, "UTF-8");
                System.out.println("URL解码后的cityName(预报): " + cityName);
            }
        } catch (Exception e) {
            System.err.println("URL解码异常(预报): " + e.getMessage());
        }

        cityName = cityName.trim();
        // 只保留常见汉字、英文字母、数字和空格
        cityName = cityName.replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9·\\s]", "");
        if (cityName.isEmpty()) return null;

        String cacheKey = Constants.WEATHER_FORECAST_CACHE_KEY + cityName;
        String cacheData = null;

        try {
            // 尝试从Redis获取缓存数据
            cacheData = redisUtil.get(cacheKey);
        if (StringUtils.hasText(cacheData)) {
                try {
            return JSON.parseObject(cacheData, WeatherForecastVO.class);
                } catch (Exception e) {
                    System.err.println("Redis预报缓存数据反序列化失败，将清除缓存: " + e.getMessage());
                    // 清除损坏的缓存数据
                    redisUtil.delete(cacheKey);
                }
            }
        } catch (Exception e) {
            System.err.println("Redis预报缓存读取异常: " + e.getMessage());
            e.printStackTrace();
            // 发生异常时，继续执行后续代码获取新数据
        }

        String cityCode = getCityCodeByCityName(cityName);
        if (cityCode == null) {
            return null;
        }

        WeatherForecastVO result = getWeatherForecastByCityCode(cityCode);
        if (result != null) {
            try {
                // 将对象转为JSON字符串存入Redis
            redisUtil.set(cacheKey, JSON.toJSONString(result), 21600); // 缓存6小时
            } catch (Exception e) {
                System.err.println("Redis预报缓存写入异常: " + e.getMessage());
                e.printStackTrace();
            }
        }
        return result;
    }

    @Override
    public void sendTemperatureReading(String temperatureReading) {

        kafkaTemplate.send("temperature", temperatureReading);
        System.out.println("发送成功");
    }

    // 私有方法：通过城市编码查询实时天气
    private WeatherRealTimeVO getCurrentWeatherByCityCode(String cityCode) {
        String cacheKey = Constants.WEATHER_REALTIME_CACHE_KEY + cityCode;
        String cacheData = redisUtil.get(cacheKey);
        if (StringUtils.hasText(cacheData)) {
            return JSON.parseObject(cacheData, WeatherRealTimeVO.class);
        }

        String apiUrl = String.format(
                "https://restapi.amap.com/v3/weather/weatherInfo?key=%s&city=%s&extensions=base",
                AMAP_KEY, cityCode
        );
        System.out.println("请求高德天气API: " + apiUrl);
        String response = HttpClientUtil.doGet(apiUrl);
        System.out.println("天气API原始响应:" + response);
        try {
        if (StringUtils.hasText(response)) {
            AmapWeatherResponse amapResp = JSON.parseObject(response, AmapWeatherResponse.class);
            if ("1".equals(amapResp.getStatus()) && !amapResp.getLives().isEmpty()) {
                AmapWeatherResponse.Live live = amapResp.getLives().get(0);
                    System.out.println("高德API返回天气数据: " + JSON.toJSONString(live));

                WeatherRealTimeVO vo = new WeatherRealTimeVO();
                vo.setProvince(live.getProvince());
                vo.setCity(live.getCity());
                vo.setAdcode(live.getAdcode());
                vo.setWeather(live.getWeather());
                vo.setTemperature(live.getTemperature());
                vo.setWindDirection(live.getWinddirection());
                vo.setWindPower(live.getWindpower());
                vo.setHumidity(live.getHumidity());
                vo.setReportTime(live.getReporttime());

                redisUtil.set(cacheKey, JSON.toJSONString(vo), 7200);
                return vo;
                } else {
                    System.err.println("高德API返回状态码异常或无数据: status=" + amapResp.getStatus());
                }
            }
        } catch (Exception e) {
            System.err.println("天气API解析异常:" + e.getMessage());
            e.printStackTrace();
            return null;
        }
        return null;
    }

    // 私有方法：通过城市编码查询天气预报
    private WeatherForecastVO getWeatherForecastByCityCode(String cityCode) {
        String cacheKey = Constants.WEATHER_FORECAST_CACHE_KEY + cityCode;
        String cacheData = redisUtil.get(cacheKey);
        if (StringUtils.hasText(cacheData)) {
            return JSON.parseObject(cacheData, WeatherForecastVO.class);
        }

        String apiUrl = String.format(
                "https://restapi.amap.com/v3/weather/weatherInfo?key=%s&city=%s&extensions=all",
                AMAP_KEY, cityCode
        );
        String response = HttpClientUtil.doGet(apiUrl);
        System.out.println("天气预报API原始响应:" + response);
        try {
        if (StringUtils.hasText(response)) {
            AmapForecastResponse amapResp = JSON.parseObject(response, AmapForecastResponse.class);
            if ("1".equals(amapResp.getStatus()) && !amapResp.getForecasts().isEmpty()) {
                AmapForecastResponse.Forecast forecast = amapResp.getForecasts().get(0);
                WeatherForecastVO vo = new WeatherForecastVO();
                vo.setProvince(forecast.getProvince());
                vo.setCity(forecast.getCity());
                vo.setAdcode(forecast.getAdcode());
                vo.setReportTime(forecast.getReporttime());

                // 转换预报详情
                vo.setForecasts(forecast.getCasts().stream()
                        .map(cast -> {
                            WeatherForecastVO.ForecastDetail detail = new WeatherForecastVO.ForecastDetail();
                            detail.setDate(cast.getDate());
                            detail.setWeek(cast.getWeek());
                            detail.setDayWeather(cast.getDayweather());
                            detail.setNightWeather(cast.getNightweather());
                            detail.setDayTemp(cast.getDaytemp());
                            detail.setNightTemp(cast.getNighttemp());
                            detail.setDayWind(cast.getDaywind());
                            detail.setNightWind(cast.getNightwind());
                            detail.setDayPower(cast.getDaypower());
                            detail.setNightPower(cast.getNightpower());
                            return detail;
                        }).collect(Collectors.toList()));

                redisUtil.set(cacheKey, JSON.toJSONString(vo), 21600);
                return vo;
            }
            }
        } catch (Exception e) {
            System.err.println("天气预报API解析异常:" + e.getMessage());
            e.printStackTrace();
            return null;
        }
        return null;
    }

    // 通过城市名称获取adcode
    private String getCityCodeByCityName(String cityName) {
        try {
            String apiUrl = String.format(
                    "%s?key=%s&address=%s&output=json",
                    GEOCODE_URL, AMAP_KEY, cityName
            );
            String response = HttpClientUtil.doGet(apiUrl);
            System.out.println("地理编码API原始响应:" + response);
            if (StringUtils.hasText(response)) {
                GeocodeResponse geocodeResp = JSON.parseObject(response, GeocodeResponse.class);
                if ("1".equals(geocodeResp.getStatus()) && !geocodeResp.getGeocodes().isEmpty()) {
                    return geocodeResp.getGeocodes().get(0).getAdcode();
                }
            }
        } catch (Exception e) {
            System.err.println("地理编码API解析异常:" + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    // 高德实时天气响应结构
    @Data
    private static class AmapWeatherResponse {
        private String status;
        private List<Live> lives;

        @Data
        public static class Live {
            private String province;
            private String city;
            private String adcode;
            private String weather;
            private String temperature;
            private String winddirection;
            private String windpower;
            private String humidity;
            private String reporttime;
        }
    }

    // 高德预报天气响应结构
    @Data
    private static class AmapForecastResponse {
        private String status;
        private List<Forecast> forecasts;

        @Data
        public static class Forecast {
            private String province;
            private String city;
            private String adcode;
            private String reporttime;
            private List<Cast> casts; // 注意字段名与API一致
        }

        @Data
        public static class Cast {
            private String date;
            private String week;
            private String dayweather;
            private String nightweather;
            private String daytemp;
            private String nighttemp;
            private String daywind;
            private String nightwind;
            private String daypower;
            private String nightpower;
        }
    }

    // 高德地理编码响应结构（新增）
    @Data
    private static class GeocodeResponse {
        private String status;
        private List<Geocode> geocodes;

        @Data
        public static class Geocode {
            private String adcode;
            private String formattedAddress;
            private String province;
            private String city;
            private String district;
            private String location;
        }
    }
}
